package com.starlinkdt.common.storage.impl;

import com.starlinkdt.common.storage.StorageInterface;
import com.starlinkdt.common.storage.config.MinioConfig;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.PutObjectOptions;
import io.minio.http.Method;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author default
 * @description： minio客户端工具类
 * @date 2025-05-23
 */
@Slf4j
@Configuration
public class MinioImpl implements StorageInterface {

    private MinioClient minioClient;

    @Autowired
    private MinioConfig minioConfig;


    private MinioClient generateClient() {
        if (Objects.isNull(minioClient)) {
            minioClient = MinioClient.builder()
                    .endpoint(minioConfig.getEndpoint())
                    .credentials(minioConfig.getAccessKeyID(), minioConfig.getSecretAccessKey())
                    .build();
        }
        return minioClient;
    }


    /**
     * 获取STS临时令牌
     *
     * @return Map
     */
    @Override
    public Map<String, Object> genStsToken() {
        Map<String, Object> ossMap = new HashMap<>(8);
        ossMap.put("securityToken", null);
        ossMap.put("accessKeyId", minioConfig.getAccessKeyID());
        ossMap.put("accessKeySecret", minioConfig.getSecretAccessKey());
        ossMap.put("endpoint", minioConfig.getEndpoint());
        ossMap.put("bucketName", minioConfig.getBucketName());

        return ossMap;

    }

    /**
     * 上传Byte数组
     *
     * @param objectName    对象路径及名称
     * @param objectContent byte数组
     */
    @SneakyThrows
    @Override
    public void putObjectByte(String objectName, byte[] objectContent) {
        MinioClient minioClient = generateClient();
        InputStream inputStream = new ByteArrayInputStream(objectContent);
        // 上传Byte数组
        minioClient.putObject(minioConfig.getBucketName(),
                objectName,
                inputStream,
                new PutObjectOptions(objectContent.length, -1));

    }

    /**
     * 上传网络流
     *
     * @param objectName 对象路径及名称
     * @param fileUrl    待上传的网络文件地址
     */
    @SneakyThrows
    @Override
    public void putObjectUrl(String objectName, String fileUrl) {
        MinioClient minioClient = generateClient();
        InputStream inputStream = new URL(fileUrl).openStream();
        minioClient.putObject(minioConfig.getBucketName(),
                objectName,
                inputStream,
                new PutObjectOptions(-1, 10485760));

    }

    /**
     * 上传文件流
     *
     * @param objectName 对象路径及名称
     * @param filePath   待上传的本地文件路径,需要指定到具体的文件名
     */
    @SneakyThrows
    @Override
    public void putObjectFile(String objectName, String filePath) {
        MinioClient minioClient = generateClient();
        InputStream inputStream = Files.newInputStream(Paths.get(filePath));
        minioClient.putObject(minioConfig.getBucketName(), objectName, inputStream, new PutObjectOptions(-1, 10485760));
    }

    /**
     * 判断文件是否存在
     *
     * @param objectName 对象路径及名称
     * @return boolean
     */
    @Override
    public boolean existObject(String objectName) {
        return false;
    }

    /**
     * 获取签名URL
     *
     * @param objectName 对象路径及名称
     * @return String
     */
    @SneakyThrows
    @Override
    public String getObjectSignUrl(String objectName) {
        // 获取minioClient实例。
        MinioClient minioClient = generateClient();
        // 设置签名URL过期时间为3600秒（1小时）
        Integer expireSeconds = minioConfig.getDurationSeconds().intValue();
        GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder()
                .bucket(minioConfig.getBucketName())
                .expiry(expireSeconds)
                .method(Method.GET)
                .object(objectName)
                .build();
        return minioClient.getPresignedObjectUrl(args);
    }

    /**
     * 下载文件流
     *
     * @param objectName 对象路径及名称
     * @return byte
     */
    @Override
    public byte[] downloadObjectStream(String objectName) {
        return new byte[0];
    }

    /**
     * 删除文件
     *
     * @param objectName 对象路径及名称
     */
    @Override
    public void deleteObject(String objectName) {

    }

    @Data
    public class ObjectItem {
        private String objectName;
        private Long size;
    }
}

